{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#类与对象\n",
    "\n",
    "class Person:\n",
    "    population = 0\n",
    "\n",
    "    def __init__(self, name):\n",
    "        self.name = name\n",
    "        print(\"(初始化…… %s)\" % self.name)\n",
    "        Person.population += 1\n",
    "\n",
    "\n",
    "    def __del__(self):\n",
    "        print(\"%s 走了。\" % self.name)\n",
    "        Person.population -= 1\n",
    "        if Person.population == 0:\n",
    "            print(\"我是最后一个人。\")\n",
    "        else:\n",
    "            print(\"还有 %d 个人在线。\" % Person.population)\n",
    "\n",
    "\n",
    "    def sayHi(self):\n",
    "        print(\"大家好！我的名字是%s\" % self.name)\n",
    "\n",
    "\n",
    "    def howMany(self):\n",
    "        if Person.population == 1:\n",
    "            print(\"只剩我一个人了\")\n",
    "        else:\n",
    "            print(\"一共有 %d 个人在这\" % Person.population)\n",
    "\n",
    "ming = Person(\"小明\")\n",
    "ming.sayHi()\n",
    "ming.howMany()\n",
    "\n",
    "hong = Person(\"小红\")\n",
    "hong.sayHi()\n",
    "hong.howMany()\n",
    "\n",
    "\n",
    "ming.sayHi()\n",
    "ming.howMany()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "香菜\n",
      "汤\n",
      "酒 开水\n"
     ]
    }
   ],
   "source": [
    "#封装：将属性和方法写到类里面\n",
    "class Mian:\n",
    "    #整个对象的共有属性\n",
    "    #属性\n",
    "        #方法 def\n",
    "        #变量 a = 1\n",
    "    attr1='汤'\n",
    "    attr2='面'\n",
    "\n",
    "one_mian = Mian()\n",
    "one_mian.attr3 = '香菜'     #私有属性\n",
    "print(one_mian.attr3)\n",
    "\n",
    "one_mian.attr1 = '酒'\n",
    "print(Mian.attr1)\n",
    "\n",
    "two_mian = Mian()\n",
    "#print(two_mian.attr3) \n",
    "\n",
    "Mian.attr1 = '开水'\n",
    "print(one_mian.attr1, two_mian.attr1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Mian:\n",
    "    flag = \"权威面店\"  # 类的变量属性(=类的全局变量)\n",
    "    # c++静态变量  共享\n",
    "\n",
    "    def __init__(self):  # self（指针） ->实例：one，two\n",
    "        self.attr1 = \"面\"  # 为实例进行初始化\n",
    "        self.attr2 = '汤'  # 实例的变量属性，默认指向当前实例对象\n",
    "\n",
    "        # self维护了这个变量和生产出来的实例之间的关系\n",
    "one = Mian()  # 实例初始化\n",
    "# 隐含了init的调用（解释器调用），为自己分配了两个私有的变量attr1， attr2\n",
    "two = Mian()\n",
    "\n",
    "print(\"第一碗面：招牌 %s，属性一：%s，属性二：%s\" %\n",
    "      (one.flag,\n",
    "       one.attr1,\n",
    "       one.attr2))\n",
    "print(\"第二碗面：招牌 %s，属性一：%s，属性二：%s\" %\n",
    "      (two.flag,\n",
    "       two.attr1,\n",
    "       two.attr2))\n",
    "print(\"_____________________________________________\\n\")\n",
    "Mian.flag = \"权威的超级面店\"\n",
    "Mian.attr1 = '开水'  # 没有修改，而是在外面创建了attr1，共享的\n",
    "# 实例的变量会覆盖掉全局同名变量\n",
    "Mian.attr3 = '香菜'\n",
    "one.attr2 = '饼干'\n",
    "print(\"第一碗面：招牌 %s，属性一：%s，属性二：%s，属性三：%s\" %\n",
    "      (one.flag,\n",
    "       one.attr1,\n",
    "       one.attr2,\n",
    "       one.attr3))\n",
    "print(\"第二碗面：招牌 %s，属性一：%s，属性二：%s\\n\" %\n",
    "      (two.flag,\n",
    "       two.attr1,\n",
    "       two.attr2))\n",
    "\n",
    "print(Mian.attr1)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 用类去创建（实例化）对象\n",
    "# 特征即属性\n",
    "# 行为即方法\n",
    "\n",
    "# 1.定义类：\n",
    "\"\"\"\n",
    "class 类名():\n",
    "    代码块\n",
    "\"\"\"\n",
    "\n",
    "class Washer():\n",
    "    def wash(self):\n",
    "        print(\"能洗衣服\")\n",
    "    def printInfo(self):\n",
    "        print(f'洗衣机的高度是{self.height}宽度是{self.width}')\n",
    "\n",
    "# 2.创建对象\n",
    "# 对象名 = 类名\n",
    "haier = Washer()\n",
    "\n",
    "# 3.验证成果\n",
    "# 打印对象\n",
    "print(haier)\n",
    "# 使用wash功能   实例方法/对象方法--对象.方法\n",
    "Washer.height = 500\n",
    "haier.width = 400\n",
    "\n",
    "haier.printInfo()\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# __init__() 方法：初始化对象 创建对象时默认调用\n",
    "class Washer():\n",
    "    def __init__(self,h,w): \n",
    "        self.height = h\n",
    "        self.width = w\n",
    "    def wash(self):\n",
    "        print(\"能洗衣服\")\n",
    "    def printInfo(self):\n",
    "        print(f'洗衣机的:\\n高度是:{self.height}\\n宽度是:{self.width}')\n",
    "\n",
    "haier = Washer(500,400)\n",
    "haier.printInfo()\n",
    "# print(Washer.heigth)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# __str__() 方法 \n",
    "# print(对象)，默认输出对象的地址，如果类定义了__str__()方法，那么将打印方法中return的数据\n",
    "\n",
    "class Washer():\n",
    "    def __str__(self):\n",
    "        return '这是海尔洗衣机的使用说明书'\n",
    "    def wash(self):\n",
    "        print(\"能洗衣服\")\n",
    "    def printInfo(self):\n",
    "        print(f'洗衣机的高度是{self.height}宽度是{self.width}')\n",
    "\n",
    "haier = Washer()\n",
    "print(haier)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Washer():\n",
    "    def __init__(self,str):\n",
    "        self.str = str\n",
    "    def __str__(self):\n",
    "        return self.str\n",
    "    def wash(self):\n",
    "        print(\"能洗衣服\")\n",
    "    def printInfo(self):\n",
    "        print(f'洗衣机的高度是{self.height}宽度是{self.width}')\n",
    "\n",
    "haier = Washer('这是海尔洗衣机的使用说明书')\n",
    "print(haier)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# __del__() 方法 ：当删除对象时，解释器也会默认调用该方法\n",
    "class Washer():\n",
    "    def __del__(self):\n",
    "        print(f'{self}对象已经被删除')\n",
    "haier = Washer()\n",
    "del haier"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 继承：子类默认继承父类的所以属性和方法\n",
    "# 父类A\n",
    "class A(object):\n",
    "#Python中，所有类默认继承object类，object类是顶级类或基类，其他子类叫派生类\n",
    "    def __init__(self):\n",
    "        self.num = 1\n",
    "    def printInfo(self):\n",
    "        print(self.num)\n",
    "\n",
    "# 子类B\n",
    "class B(A):\n",
    "    pass\n",
    "\n",
    "result = B()\n",
    "result.printInfo()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#单继承\n",
    "# 1.师傅类\n",
    "class Master(object):\n",
    "    def __init__(self):\n",
    "        self.kongfu = \"[古法煎饼果子配方]\"\n",
    "\n",
    "    def makeCake(self):\n",
    "        print(f'运用{self.kongfu}制作煎饼果子')\n",
    "\n",
    "# 2.学徒类\n",
    "class Prentice(Master):\n",
    "    pass\n",
    "\n",
    "daqiu = Prentice()\n",
    "daqiu.makeCake()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 多继承 ：一个类同时继承多个父类\n",
    "# 1.师傅类\n",
    "class Master(object):\n",
    "    def __init__(self):\n",
    "        self.kongfu = \"[古法煎饼果子配方]\"\n",
    "    def makeCake(self):\n",
    "        print(f'运用{self.kongfu}制作煎饼果子')\n",
    "\n",
    "# 2.学校类\n",
    "class School():#默认继承object\n",
    "    def __init__(self):\n",
    "        self.kongfu = \"[黑马煎饼果子配方]\"\n",
    "        def makeCake(self):\n",
    "            print(f'运用{self.kongfu}制作煎饼果子')\n",
    "\n",
    "class Prentice(School,Master):      #默认使用第一个父类的同名属性和方法\n",
    "    pass\n",
    "\n",
    "daqiu = Prentice()\n",
    "daqiu.makeCake()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 子类重写父类同名方法和属性   __mor__\n",
    "class Master(object):\n",
    "    def __init__(self):\n",
    "        self.kongfu = \"[古法煎饼果子配方]\"\n",
    "    def makeCake(self):\n",
    "        print(f'运用{self.kongfu}制作煎饼果子')\n",
    "\n",
    "# 2.学校类\n",
    "class School():#默认继承object\n",
    "    def __init__(self):\n",
    "        self.kongfu = \"[黑马煎饼果子配方]\"\n",
    "    def makeCake(self):\n",
    "        print(f'运用{self.kongfu}制作煎饼果子')\n",
    "\n",
    "class Prentice(School,Master):\n",
    "    def __init__(self):\n",
    "        self.kongfu = \"[独创煎饼果子配方]\"\n",
    "    def makeCake(self):\n",
    "        print(f'运用{self.kongfu}制作煎饼果子')\n",
    "\n",
    "daqiu = Prentice()\n",
    "daqiu.makeCake()        #调用到的是子类的属性和方法\n",
    "\n",
    "print(Prentice.__mro__) #打印当前类的继承关系"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 子类调用父类同名方法和属性\n",
    "class Master(object):\n",
    "    def __init__(self):\n",
    "        self.kongfu = \"[古法煎饼果子配方]\"\n",
    "\n",
    "    def makeCake(self):\n",
    "        print(f'运用{self.kongfu}制作煎饼果子')\n",
    "\n",
    "\n",
    "class School():  # 默认继承object\n",
    "    def __init__(self):\n",
    "        self.kongfu = \"[黑马煎饼果子配方]\"\n",
    "\n",
    "    def makeCake(self):\n",
    "        print(f'运用{self.kongfu}制作煎饼果子')\n",
    "\n",
    "\n",
    "class Prentice(School, Master):\n",
    "    def __init__(self):\n",
    "        self.kongfu = \"[独创煎饼果子配方]\"\n",
    "\n",
    "    def makeCake(self):\n",
    "        # 如果先调用了父类的属性和方法，父类的会覆盖子类的，故先调用子类自己的初始化\n",
    "        self.__init__() #不加则为上一次初始化结果\n",
    "        print(f'运用{self.kongfu}制作煎饼果子')\n",
    "    \n",
    "\n",
    "    def makeMasterCake(self):   # 再次封装\n",
    "        Master.__init__(self)   # 调用父类方法，但是为保证调用到的也是父类1属性，必须在调用方法前调用父类的初始化\n",
    "        Master.makeCake(self)\n",
    "\n",
    "    def makeSchoolCake(self):  # 方法名随意\n",
    "        School.__init__(self)\n",
    "        School.makeCake(self)\n",
    "\n",
    "\n",
    "daqiu = Prentice()\n",
    "daqiu.makeCake()\n",
    "daqiu.makeMasterCake()\n",
    "daqiu.makeSchoolCake()\n",
    "\n",
    "daqiu.makeCake()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 多层继承 (Master,School)-->Prentice--->Tusun\n",
    "class Master(object):\n",
    "    def __init__(self):\n",
    "        self.kongfu = \"[古法煎饼果子配方]\"\n",
    "\n",
    "    def makeCake(self):\n",
    "        print(f'运用{self.kongfu}制作煎饼果子')\n",
    "\n",
    "\n",
    "class School():  # 默认继承object\n",
    "    def __init__(self):\n",
    "        self.kongfu = \"[黑马煎饼果子配方]\"\n",
    "\n",
    "    def makeCake(self):\n",
    "        print(f'运用{self.kongfu}制作煎饼果子')\n",
    "\n",
    "\n",
    "class Prentice(School, Master):\n",
    "    def __init__(self):\n",
    "        self.kongfu = \"[独创煎饼果子配方]\"\n",
    "\n",
    "    def makeCake(self):\n",
    "        # 如果先调用了父类的属性和方法，父类的会覆盖子类的，故先调用子类自己的初始化\n",
    "        self.__init__() #不加则为上一次初始化结果\n",
    "        print(f'运用{self.kongfu}制作煎饼果子')\n",
    "    # 调用父类方法，但是为保证调用到的也是父类1属性，必须在调用方法前调用父类的初始化\n",
    "\n",
    "    def makeMasterCake(self):\n",
    "        Master.__init__(self)\n",
    "        Master.makeCake(self)\n",
    "\n",
    "    def makeSchoolCake(self):  # 方法名随意\n",
    "        School.__init__(self)\n",
    "        School.makeCake(self)\n",
    "# 1.创建Tusun类    2.用这个类创建对象   3.用这个对象调用父类的方法和属性\n",
    "# 徒孙类\n",
    "class Tusun(Prentice):\n",
    "    pass\n",
    "\n",
    "xiaoqiu = Tusun()\n",
    "\n",
    "xiaoqiu.makeCake()\n",
    "xiaoqiu.makeMasterCake()\n",
    "xiaoqiu.makeSchoolCake()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# super() 调用父类方法 super()可自动查找父类。调用顺序遵循__mro__类属性的顺序。比较适合单继承使用\n",
    "class Master(object):\n",
    "    def __init__(self):\n",
    "        self.kongfu = \"[古法煎饼果子配方]\"\n",
    "\n",
    "    def makeCake(self):\n",
    "        print(f'运用{self.kongfu}制作煎饼果子')\n",
    "\n",
    "\n",
    "class School(Master): \n",
    "    def __init__(self):\n",
    "        self.kongfu = \"[黑马煎饼果子配方]\"\n",
    "\n",
    "    def makeCake(self):\n",
    "        print(f'运用{self.kongfu}制作煎饼果子')\n",
    "\n",
    "        # 方法2.1 super(当前类名,self).函数名()\n",
    "        # super(School,self).__init__()\n",
    "        # super(School,self).makeCake()\n",
    "\n",
    "        # 方法2.2 super().函数()\n",
    "        super().__init__()\n",
    "        super().makeCake()\n",
    "\n",
    "\n",
    "class Prentice(School):\n",
    "    def __init__(self):\n",
    "        self.kongfu = \"[独创煎饼果子配方]\"\n",
    "\n",
    "    def makeCake(self):\n",
    "        self.__init__() \n",
    "        print(f'运用{self.kongfu}制作煎饼果子')\n",
    "    \n",
    "\n",
    "    def makeMasterCake(self):\n",
    "        Master.__init__(self)\n",
    "        Master.makeCake(self)\n",
    "\n",
    "    def makeSchoolCake(self): \n",
    "        School.__init__(self)\n",
    "        School.makeCake(self)\n",
    "\n",
    "    def makeOldCake(self):\n",
    "        # 方法一：代码冗余\n",
    "        # Master.__init__(self)\n",
    "        # Master.makeCake(self)\n",
    "        # School.__init__(self)\n",
    "        # School.makeCake(self)\n",
    "\n",
    "        # 方法二：super()\n",
    "        # 方法2.1 super(当前类名,self).函数名()\n",
    "        # super(Prentice,self).__init__()\n",
    "        # super(Prentice,self).makeCake()\n",
    "\n",
    "        # 方法2.2 super().函数()\n",
    "        super().__init__()\n",
    "        super().makeCake()\n",
    "\n",
    "# 徒孙类\n",
    "class Tusun(Prentice):\n",
    "    pass\n",
    "\n",
    "xiaoqiu = Tusun()\n",
    "\n",
    "# xiaoqiu.makeCake()\n",
    "# xiaoqiu.makeMasterCake()\n",
    "# xiaoqiu.makeSchoolCake()\n",
    "xiaoqiu.makeOldCake()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 私有权限：私有属性和方法 不继承给子类\n",
    "# 设置私有权限：在属性或者方法名前面加上两个下划线__.\n",
    "class Master(object):\n",
    "    def __init__(self):\n",
    "        self.kongfu = \"[古法煎饼果子配方]\"\n",
    "\n",
    "    def makeCake(self):\n",
    "        print(f'运用{self.kongfu}制作煎饼果子')\n",
    "\n",
    "\n",
    "class School():\n",
    "    def __init__(self):\n",
    "        self.kongfu = \"[黑马煎饼果子配方]\"\n",
    "\n",
    "    def makeCake(self):\n",
    "        print(f'运用{self.kongfu}制作煎饼果子')\n",
    "\n",
    "\n",
    "class Prentice(School, Master):\n",
    "    def __init__(self):\n",
    "        self.kongfu = \"[独创煎饼果子配方]\"  # 公有属性\n",
    "        self.__money = 2000000  # 定义私有属性\n",
    "\n",
    "    def __PrintInfo(self):  # 私有方法\n",
    "        print(\"这是私有方法\")\n",
    "\n",
    "    def printInfo(self):\n",
    "        print(self.kongfu)\n",
    "        print(self.__money)\n",
    "\n",
    "    def makeCake(self):\n",
    "        self.__init__()\n",
    "        print(f'运用{self.kongfu}制作煎饼果子')\n",
    "\n",
    "    def makeMasterCake(self):\n",
    "        Master.__init__(self)\n",
    "        Master.makeCake(self)\n",
    "\n",
    "    def makeSchoolCake(self):\n",
    "        School.__init__(self)\n",
    "        School.makeCake(self)\n",
    "\n",
    "\n",
    "class Tusun(Prentice):\n",
    "    pass\n",
    "\n",
    "\n",
    "daqiu = Prentice()     # 对象不能访问私有属性\n",
    "# print(daqiu.__money)\n",
    "# print(daqiu.__PrintInfo)\n",
    "\n",
    "xiaoqiu = Tusun()   #子类不能继承私有属性\n",
    "# print(xiaoqiu.__money)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#获取和修改私有属性 用get_xx获取私有属性 用set_xx修改属性(自定义函数)\n",
    "# 私有权限：私有属性和方法 不继承给子类\n",
    "# 设置私有权限：在属性或者方法名前面加上两个下划线__.\n",
    "class Master(object):\n",
    "    def __init__(self):\n",
    "        self.kongfu = \"[古法煎饼果子配方]\"\n",
    "\n",
    "    def make_ake(self):\n",
    "        print(f'运用{self.kongfu}制作煎饼果子')\n",
    "\n",
    "\n",
    "class School():\n",
    "    def __init__(self):\n",
    "        self.kongfu = \"[黑马煎饼果子配方]\"\n",
    "\n",
    "    def make_cake(self):\n",
    "        print(f'运用{self.kongfu}制作煎饼果子')\n",
    "\n",
    "\n",
    "class Prentice(School, Master):\n",
    "    def __init__(self):\n",
    "        self.kongfu = \"[独创煎饼果子配方]\"  # 公有属性\n",
    "        self.__money = 2000000  # 定义私有属性\n",
    "    \n",
    "    # 获取私有属性\n",
    "    def get_money(self):\n",
    "        return self.__money\n",
    "\n",
    "    # 修改私有属性\n",
    "    def set_money(self, value):\n",
    "        self.__money = value\n",
    "\n",
    "    def __print_info(self):  # 私有方法\n",
    "        print(\"这是私有方法\")\n",
    "\n",
    "    def print_info(self):\n",
    "        print(self.kongfu)\n",
    "        print(self.__money)\n",
    "\n",
    "    def make_cake(self):\n",
    "        self.__init__()\n",
    "        print(f'运用{self.kongfu}制作煎饼果子')\n",
    "\n",
    "    def make_Master_cake(self):\n",
    "        Master.__init__(self)\n",
    "        Master.makeCake(self)\n",
    "\n",
    "    def make_School_cake(self):\n",
    "        School.__init__(self)\n",
    "        School.makeCake(self)\n",
    "\n",
    "\n",
    "class Tusun(Prentice):\n",
    "    pass\n",
    "\n",
    "\n",
    "daqiu = Prentice()\n",
    "xiaoqiu = Tusun()\n",
    "\n",
    "print(xiaoqiu.get_money())\n",
    "xiaoqiu.set_money(250)\n",
    "print(xiaoqiu.get_money())\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 多态：传入不同对象，产生不同结果（不是一定要依赖继承）  \n",
    "### 多态定义：多态是一种使用对象的方式，子类重写父类方法，调用不同类对象的相同方法可以产生不同的执行结果  \n",
    "### 实现步骤：  \n",
    "### 1.定义父类，并提供公共方法  \n",
    "### 2.定义子类，并重写父类方法  \n",
    "### 3.传递子类调用对象给调用者，可以看到不同子类执行效果不同  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 多态\n",
    "class Dog():\n",
    "    def work(self):     #父类提供统一方法，哪怕是空方法（pass）\n",
    "        print(\"指哪打哪……\")\n",
    "\n",
    "class Armydog(Dog):     #继承\n",
    "    def work(self):     #子类重写父类同名方法\n",
    "        print(\"追击敌人……\")\n",
    "    \n",
    "class DrugDog(Dog):\n",
    "    def work(self):\n",
    "        print(\"追查毒品……\")\n",
    "\n",
    "class Person():\n",
    "    def work_with_dog(self,dog):        # 传入不同对象，执行不同代码\n",
    "        dog.work()\n",
    "\n",
    "ad = Armydog()\n",
    "dd = DrugDog()\n",
    "\n",
    "daqiu = Person()\n",
    "daqiu.work_with_dog(ad)\n",
    "daqiu.work_with_dog(dd)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 类属性就是 类对象 所拥有的属性，它被 该类的所有实例对象 所拥有\n",
    "# 设置·访问·修改\n",
    "\n",
    "class Dog:\n",
    "    tooth = 10 \n",
    "\n",
    "wangcai = Dog()\n",
    "xiaohei = Dog()\n",
    "\n",
    "# 访问类属性\n",
    "print(Dog.tooth)\n",
    "print(wangcai.tooth)\n",
    "print(xiaohei.tooth)\n",
    "\n",
    "# 修改类属性\n",
    "Dog.tooth = 12\n",
    "print(Dog.tooth)\n",
    "print(wangcai.tooth)\n",
    "print(xiaohei.tooth)\n",
    "\n",
    "# 不能通过对象修改属性，如果这样操作，实则是创建了一个实例属性（对象属性）\n",
    "wangcai.tooth = 8\n",
    "print(Dog.tooth)\n",
    "print(wangcai.tooth)\n",
    "print(xiaohei.tooth)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 类方法\n",
    "# 需要用装饰器 @classmethod 来标记其为类方法，对于类方法：第一个参数必须是类对象，一帮以cls作为第一个参数\n",
    "class Dog:\n",
    "    __tooth = 10        # 当方法中 需要使用类对象（如操作私有属性） 时，定义类方法\n",
    "                        # 类方法一般和类属性配合使用\n",
    "    @classmethod\n",
    "    def get_tooth(cls):\n",
    "        return cls.__tooth\n",
    "\n",
    "wangcai = Dog()\n",
    "wangcai.get_tooth()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "这是一个狗类，用于创建狗对象……\n",
      "这是一个狗类，用于创建狗对象……\n"
     ]
    }
   ],
   "source": [
    "# 静态方法\n",
    "# 需要通过装饰器 @staticmethod 来进行修饰，静态方法既不需要传递类对象也不需要传递实例对象（形参没有self/cls）\n",
    "# 能够通过实例对象和类对象去访问\n",
    "# 减少不必要消耗\n",
    "class Dog:\n",
    "    @staticmethod\n",
    "    def printInfo():\n",
    "        print(\"这是一个狗类，用于创建狗对象……\")\n",
    "\n",
    "wangcai = Dog()\n",
    "\n",
    "Dog.printInfo()\n",
    "wangcai.printInfo()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "try:\n",
    "    可能发生异常的代码\n",
    "except:\n",
    "    捕获到异常该执行的代码\n",
    "\n",
    "try:\n",
    "    fo = open('text.txt','r')\n",
    "except:\n",
    "    fo = open('text.txt','w')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "出错啦！\n"
     ]
    }
   ],
   "source": [
    "# 捕获多个异常\n",
    "try:\n",
    "    print(1/0)\n",
    "except(NameError, ZeroDivisionError):\n",
    "    print(\"出错啦！\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "division by zero\n"
     ]
    }
   ],
   "source": [
    "# 捕获异常描述信息\n",
    "try:\n",
    "    print(1/0)\n",
    "    \n",
    "except (NameError, ZeroDivisionError) as result:\n",
    "    print(result)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "division by zero\n"
     ]
    }
   ],
   "source": [
    "# 捕获所有异常\n",
    "try:\n",
    "    print(1/0)\n",
    "    \n",
    "except Exception as result:\n",
    "    print(result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "你输入的长度是3, 不能少于6\n"
     ]
    }
   ],
   "source": [
    "# 自定义异常\n",
    "class ShortInputError(Exception):\n",
    "    def __init__(self, length, minLen):\n",
    "        self.length = length\n",
    "        self.minLen = minLen\n",
    "\n",
    "    # 设置异常描述信息\n",
    "    def __str__(self):\n",
    "        return f'你输入的长度是{self.length}, 不能少于{self.minLen}'\n",
    "\n",
    "\n",
    "def main():\n",
    "    try:\n",
    "        mima = input(\"请输入密码：\")\n",
    "        min = 6\n",
    "        if len(mima) < min:\n",
    "            raise ShortInputError(len(mima), min) #抛出异常：raise 异常类名()\n",
    "    except Exception as result:\n",
    "        print(result)\n",
    "    else:\n",
    "        print(\"密码输入完成\")\n",
    "\n",
    "\n",
    "main()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 模块（Module）是一个以.py结尾的Python文件，包含Python对象定义和Python语句\n",
    "# 制作模块：1.定义 2.测试 3.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# __all__\n",
    "# 如果一个模块文件中有__all__变量，当使用from  import *时，只能导入这个列表中的元素\n",
    "\n",
    "# 模块代码 my_module.py\n",
    "__all__ = ['testA']\n",
    "\n",
    "def testA():\n",
    "    print('testA')\n",
    "def testB():\n",
    "    print('testB')\n",
    "\n",
    "\n",
    "#导入代码\n",
    "from my_module import*\n",
    "testA() # 正确\n",
    "testB() # 错误"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 包：将有联系的模块放到同一文件夹下，并在文件夹中创建__init__.py\n",
    "# 导入包; import 包名.模块名\n",
    "#         包名.模块名.目标"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 二维向量\n",
    "import math\n",
    "\n",
    "\n",
    "class Vec2D(object):\n",
    "    def __init__(self, x=0, y=0):\n",
    "        self.__x = x\n",
    "        self.__y = y\n",
    "\n",
    "    def getX(self):\n",
    "        return self.__x\n",
    "\n",
    "    def getY(self):\n",
    "        return self.__y\n",
    "\n",
    "    def __del__(self):\n",
    "        del self.__x\n",
    "        del self.__y\n",
    "\n",
    "    def __iadd__(self, vec2d):\n",
    "        self.__x += vec2d.getX()\n",
    "        self.__y += vec2d.getY()\n",
    "        return self\n",
    "\n",
    "    def __add__(self, vec2d):\n",
    "        vec2d_temp = self\n",
    "        return vec2d_temp.__iadd__(vec2d)\n",
    "\n",
    "    def __isub__(self, vec2d):\n",
    "        self.__x -= vec2d.getX()\n",
    "        self.__y -= vec2d.getY()\n",
    "        return self\n",
    "\n",
    "    def __sub__(self, vec2d):\n",
    "        vec2d_temp = self\n",
    "        return vec2d_temp.__isub__(vec2d)\n",
    "\n",
    "    def __imul__(self, vec2d):\n",
    "        return self.__x*vec2d.getx()+self.__y*vec2d.getY()\n",
    "\n",
    "    def __mul__(self, vec2d):\n",
    "        self.__mul__(vec2d)\n",
    "\n",
    "    @property\n",
    "    def norm(self):\n",
    "        \"\"\" 返回向量的范数 \"\"\"\n",
    "        return math.sqrt(self.__x**2+self.__y**2)\n",
    "\n",
    "    def __str__(self):  # 字符串打印\n",
    "        return f\"({self.__x}, {self.__y})\"\n",
    "\n",
    "    def __getitem__(self, pos):\n",
    "        \"\"\" 按下标取值 \"\"\"\n",
    "        return [self.__x, self.__y][pos]\n",
    "\n",
    "    def __ne__(self, vec2d):\n",
    "        return self.norm != vec2d.norm\n",
    "\n",
    "    def __eq__(self, vec2d):\n",
    "        return self.__x == vec2d.getX() and self.__y == vec2d.getY()\n",
    "\n",
    "    __repr__ = __str__  # 解释器打印\n",
    "\n",
    "\n",
    "v1 = Vec2D(1, 2)\n",
    "v2 = Vec2D(4, 3)\n",
    "v3 = Vec2D(3, 4)\n",
    "# print(v2.norm)\n",
    "# print(v2[1])\n",
    "# v3 == v2\n",
    "v1-v2\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from math import pi\n",
    "\n",
    "class Circle(object):\n",
    "    _radius = 0\n",
    "\n",
    "    def __init__(self, r) -> None:\n",
    "        self._radius = r\n",
    "\n",
    "    def SetRadius(self, r):\n",
    "        self._radius = r\n",
    "\n",
    "    def GetRadius(self):\n",
    "        return float(self._radius)\n",
    "\n",
    "    def GetCircumference(self):\n",
    "        return 2*pi*self._radius\n",
    "\n",
    "    def GetArea(self):\n",
    "        return pi*self._radius*self._radius\n",
    "\n",
    "    def __del__(self):\n",
    "        print(f'{self}对象已经被删除')\n",
    "\n",
    "\n",
    "class SolidSphere(Circle):\n",
    "    _radius = 0\n",
    "\n",
    "    def GetCircumference(self):\n",
    "        return 2*pi*self._radius\n",
    "\n",
    "    def GetArea(self):\n",
    "        return 4*pi*self._radius*self._radius\n",
    "\n",
    "    def GetVolume(self):\n",
    "        return 4/3*pi*self._radius*self._radius*self._radius\n",
    "\n",
    "\n",
    "c1 = Circle(12.5)\n",
    "print(c1.GetRadius())\n",
    "print(c1.GetCircumference())\n",
    "print(c1.GetArea())\n",
    "print()\n",
    "s1 = SolidSphere(5)\n",
    "print(s1.GetRadius())\n",
    "print(s1.GetCircumference())\n",
    "print(s1.GetArea())\n",
    "print(s1.GetVolume())\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Root:\n",
    "    __total = 0\n",
    "\n",
    "    def __init__(self, v):\n",
    "        self.__value = v\n",
    "        Root.__total += 1\n",
    "\n",
    "    def show(self):\n",
    "        print(\"self.__value = \", self.__value)\n",
    "        print(\"Root.__total = \", Root.__total)\n",
    "    \n",
    "    def __get(self):\n",
    "        return self.__value\n",
    "    \n",
    "    def __set(self,v):\n",
    "        self.__value=v\n",
    "    \n",
    "    def __del(self):\n",
    "        del self.__value\n",
    "\n",
    "    value=property(__get,__set,__del)\n",
    "\n",
    "    @classmethod\n",
    "    def classShowTotal(cls):\n",
    "        print(cls.__total)\n",
    "\n",
    "    @staticmethod\n",
    "    def staticShoowTotal():\n",
    "        print(Root.__total)\n",
    "\n",
    "\n",
    "r = Root(3)\n",
    "r.show()\n",
    "r.value\n",
    "Root.classShowTotal()\n",
    "Root.staticShoowTotal()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.9.1 64-bit",
   "metadata": {
    "interpreter": {
     "hash": "78a022ac77446f354d31e836af73f58b0c1bbd5e689bddf81efabb290314bc59"
    }
   },
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.1-final"
  },
  "orig_nbformat": 2
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
